﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WasaWasa.Controls;
using System.Net;
using System.IO;
using System.Web;
using System.Windows.Controls.Primitives;
using System.Timers;
using System.Diagnostics;

using Res = WasaWasa.Properties.Resources;
using System.ComponentModel;

namespace WasaWasa
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        Properties.Settings def = Properties.Settings.Default;
        Properties.WindowStateSettings wss = Properties.WindowStateSettings.Default;

        SettingsWindow wndSttings;
        PictogramPaletteWindow wndPictogramPelette;
        Dictionary<object, ScrollViewer> scrollViewers;

        private string WindowTitle
        {
            get { return def.UserName + " - " + Res.StringProductLocalName; }
        }

        public MainWindow()
        {
            def.Upgrade();
            wss.Upgrade();

            Resources["applicationSettings"] = def;

            def.PropertyChanged += new PropertyChangedEventHandler(def_PropertyChanged);

            this.Title = WindowTitle;

            this.WindowState = wss.WindowState;
            this.Height = wss.Height;
            this.Width = wss.Width;
            this.Top = wss.Top;
            this.Left = wss.Left;

            scrollViewers = new Dictionary<object, ScrollViewer>();

            InitializeComponent();
            InitializeCommonMethods();
            InitializeUpdateTab();
            InitializeTimelineTab();
            InitializeUserListTab();
            InitializeTodoTab();
        }

        void def_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.Title = WindowTitle;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeTimer();
            InitializeTwitter();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            FinalizeTwitter();

            if (MessageBox.Show(Res.QuestionExit, Res.OperationExit, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
            {
                e.Cancel = true;
                return;
            }

            wss.WindowState = WindowState;
            wss.Top = Top;
            wss.Left = Left;
            wss.Height = ActualHeight;
            wss.Width = ActualWidth;
            wss.Save();
        }

        partial void InitializeCommonMethods();
        partial void InitializeTimer();
        partial void InitializeUpdateTab();
        partial void InitializeTimelineTab();
        partial void InitializeUserListTab();
        partial void InitializeTodoTab();

        private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            try
            {
                Process.Start(e.Uri.ToString());
            }
            catch (Win32Exception) { } //TODO:
        }

        #region ListBoxのスクロールの実装
        private void ScrollViewer_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            ScrollViewer sv = scrollViewers[sender];
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                if (0 < e.Delta)
                    this.FontSize++;
                else
                    this.FontSize--;
            }
            else if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
            {
                if (0 < e.Delta)
                    sv.PageUp();
                else
                    sv.PageDown();
            }
            else
            {
                if (0 < e.Delta)
                    sv.LineUp();
                else
                    sv.LineDown();
            }
            e.Handled = true;
        }

        private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (!scrollViewers.ContainsValue(e.OriginalSource as ScrollViewer))
            {
                ScrollViewer sv = e.OriginalSource as ScrollViewer;
                scrollViewers[sender] = e.OriginalSource as ScrollViewer;
            }
        }
        #endregion

        #region 操作時自動読込の実装
        private void tabsMain_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
#if DEBUG
#else
            if (e.AddedItems.Count <= 0) return;
            Object o = e.AddedItems[0];
            do
            {
                TimelineBundle b = o as TimelineBundle;
                if (b == null) break;
                if (!b.IsLoaded)
                    LoadTimeline(b);
            } while (false);
            do
            {
                UserListBundle b = o as UserListBundle;
                if (b == null) break;
                if (!b.IsLoaded)
                    LoadUserList(b);
            } while (false);
#endif
        }

        private void tabsTimeline_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((replyType & ReplyType.Status) == ReplyType.Status || (replyType & ReplyType.User) == ReplyType.User)
                return;
            if (e.AddedItems.Count <= 0) return;
            TimelineBundle b = e.AddedItems[0] as TimelineBundle;
            if (b == null) return;
            if (b.Type == TimelineType.Channel)
            {
                ClearReplyInfo();
                replyType = ReplyType.Channel;
                replyTimeline = tabsTimeline.SelectedItem as TimelineBundle;
                txtReplyTarget.ToolTip = txtReplyTarget.Text = string.Format("#{0}({1}) ", replyTimeline.Tags["NameEn"], replyTimeline.Tags["Title"]);
            }
            else
            {
                ClearReplyInfo();
            }
        }
        #endregion

        #region 自動リンク・絵文字の実装
        private void replacableTextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            TextBlock tb = sender as TextBlock;
            if (tb.Inlines.Count > 0) return;
            StatusClass status = tb.DataContext as StatusClass;
            UserClass user = tb.DataContext as UserClass;
            if (status == null && user == null) return;
            tb.Inlines.AddRange(StatusClass.GenerateInlines(
                tb.Name == "txtStatusNick" ? status.Nick :
                tb.Name == "txtStatusText" ? status.Text :
                tb.Name == "txtReplyUserNick" && status.ReplyUserNick != null ? status.ReplyUserNick :
                tb.Name == "txtReplyMessage" && status.ReplyMessage != null ? status.ReplyMessage :
                tb.Name == "txtUserNick" ? user.Nick : ""));
        }
        #endregion

        #region コマンドの実装
        private void showPictogramPeletteCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (wndPictogramPelette == null)
            {
                wndPictogramPelette = new PictogramPaletteWindow()
                {
                    Owner = this,
                };
                wndPictogramPelette.PictogramInputed += new EventHandler<ObjectEventArgs<int>>(wndPictogramPelette_PictogramInputed);
                wndPictogramPelette.Show();
            }
            else
            {
                if (wndPictogramPelette.IsVisible)
                {
                    wndPictogramPelette.Hide();
                }
                else
                {
                    wndPictogramPelette.Show();
                }
            }
        }

        private void propertyCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (wndSttings == null)
            {
                wndSttings = new SettingsWindow()
                {
                    Owner = this,
                };
                wndSttings.Closed += new EventHandler(delegate(object sender2, EventArgs e2)
                {
                    wndSttings = null;
                });
                wndSttings.Show();
            }
            else if (wndSttings.IsVisible == true)
            {
                wndSttings.Activate();
            }
        }

        private void updateStatusCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !string.IsNullOrEmpty(txtUpdate.Text) && txtUpdate.IsVisible;
        }

        private void updateStatusCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            UpdateStatus();
        }

        private void copyCommandBindingOfTimeline_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = 0 <= (sender as ListBox).SelectedIndex;
        }

        private void copyCommandBindingOfTimeline_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            StatusClass status = (sender as ListBox).SelectedItem as StatusClass;
            Clipboard.SetText(string.Format("{0}({1})\r\n{4}{2}\r\n{3}\r\n", status.LoginId, status.Nick, status.Text, status.DateTime,
                (status.ReplyUserLoginId != null ? string.Format(">{0}({1})\r\n>{2}\r\n", status.ReplyUserLoginId, status.ReplyUserNick, status.ReplyMessage) : "")));
        }

        private void clearReplyInfoCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = replyType != ReplyType.NotReply;
        }

        private void clearReplyInfoCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ClearReplyInfo();
        }

        private void loadCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            switch (tabsMain.SelectedIndex)
            {
                case 0:
                    LoadTimeline(tabsTimeline.SelectedItem as TimelineBundle);
                    break;
                case 1:
                    LoadUserList(tabsUserlist.SelectedItem as UserListBundle);
                    break;
                case 2:
                    break;
            }
        }

        private void loadTimelineCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LoadTimeline(tabsTimeline.SelectedItem as TimelineBundle);
        }

        private void loadUserListCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LoadUserList(tabsUserlist.SelectedItem as UserListBundle);
        }

        private void loadTodoCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void loadChannelListCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            LoadChannelList();
        }

        private void replyToStatusCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            e.CanExecute = b.Type != TimelineType.Channel && 0 <= b.SelectedIndex;
        }

        private void replyToStatusCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ClearReplyInfo();
            replyType = ReplyType.General | ReplyType.Status;
            replyTimeline = tabsTimeline.SelectedItem as TimelineBundle;
            replyStatus = replyTimeline.SelectedItem;
            txtReplyTarget.Text = ">" + (txtReplyTarget.ToolTip = replyStatus.Text);
            expUpdate.IsExpanded = true;
            txtUpdate.Focus();
        }

        private void replyToUserCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            e.CanExecute = 0 <= b.SelectedIndex;
        }

        private void replyToUserCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ClearReplyInfo();
            string target = "";
            replyType |= ReplyType.User;
            replyTimeline = tabsTimeline.SelectedItem as TimelineBundle;
            if ((tabsTimeline.SelectedItem as TimelineBundle).Type == TimelineType.Channel)
            {
                replyType |= ReplyType.Channel;
                target += string.Format("#{0}({1}) ", replyTimeline.Tags["NameEn"], replyTimeline.Tags["Title"]);
            }
            else
            {
                replyType |= ReplyType.General;
            }
            StatusClass status = replyTimeline.SelectedItem;
            replyUser = status.LoginId;
            txtReplyTarget.ToolTip = txtReplyTarget.Text = target + string.Format("@{0}({1})", status.LoginId, status.Nick);
            expUpdate.IsExpanded = true;
            txtUpdate.Focus();
        }

        private void createFavoriteCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            e.CanExecute = 0 <= b.SelectedIndex;
        }

        private void createFavoriteCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            CreateFavorite(b.SelectedItem.Rid);
        }

        private void destroyFavoriteCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            e.CanExecute = 0 <= b.SelectedIndex;
        }

        private void destroyFavoriteCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            TimelineBundle b = tabsTimeline.SelectedItem as TimelineBundle;
            DestroyFavorite(b.SelectedItem.Rid);
        }

        private void createFollowCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = 0 <= (tabsUserlist.SelectedItem as UserListBundle).SelectedIndex;
        }

        private void createFollowCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            UserClass user = (tabsUserlist.SelectedItem as UserListBundle).SelectedItem;
            if (MessageBox.Show(string.Format(Res.QuestionCreateFollow, user.LoginId, user.Nick), Res.OperationCreateFollow, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                CreateFollow(user.LoginId);
            }
        }

        private void createFollowSpecifiedIdCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            PromptDialog pd = new PromptDialog()
            {
                Title = Res.PromptUserId,
            };
            if (pd.ShowDialog() == true)
            {
                CreateFollow(pd.Text);
            }
        }

        private void destroyFollowCommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = 0 <= (tabsUserlist.SelectedItem as UserListBundle).SelectedIndex;
        }

        private void destroyFollowCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            UserClass user = (tabsUserlist.SelectedItem as UserListBundle).SelectedItem;
            if (MessageBox.Show(string.Format(Res.QuestionDestroyFollow, user.LoginId, user.Nick), Res.OperationDestroyFollow, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                DestoryFollow(user.LoginId);
            }
        }
        #endregion

        void wndPictogramPelette_PictogramInputed(object sender, ObjectEventArgs<int> e)
        {
            txtUpdate.Text += char.ConvertFromUtf32(e.Value);
        }

        private void miSplitDropDown_Loaded(object sender, RoutedEventArgs e)
        {
            MenuItem mi = sender as MenuItem;
            ((mi.TemplatedParent as ContentPresenter).TemplatedParent as Button).Click += new RoutedEventHandler(delegate(object sender2, RoutedEventArgs e2)
            {
                mi.IsSubmenuOpen = true;
            });
        }

        private void exitCommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }
    }
}
